﻿using System;
using System.Globalization;
using System.IO;
using System.Xml;
using Microsoft.SqlServer.Dts.Runtime;

namespace ForEachWatchedFileEnumerator
{
    public enum WatchedFolderPathSource
    {
        DirectInput,
        Variable,
        ConnectionManager
    }

    public enum FileSpecSource
    {
        DirectInput,
        Variable
    }

    [DtsForEachEnumerator(
    DisplayName = "File Watcher Enumerator",
    Description = "File Watcher Enumerator",
    UITypeName = "ForEachWatchedFileEnumerator.ForEachWatchedFileUI,ForEachWatchedFileEnumerator,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=4c9ffe9eee716762"
    )]
    public class ForEachWatchedFile : ForEachEnumerator, IDTSComponentPersist
    {

        public WatchedFolderPathSource WatchFolderPathSource { get; set; }
        public string WatchFolderPath { get; set; }
        public FileSpecSource FileSpecSource { get; set; }
        public string FileSpec { get; set; }
        public int TimeOut { get; set; }
        public bool IncludeSubdirectories { get; set; }
        public bool ProcessExistingFiles { get; set; }


        public override object GetEnumerator(Connections connections, VariableDispenser variableDispenser, IDTSInfoEvents events,
            IDTSLogging log)
        {

            string watchFolderPath = "";

            if (WatchFolderPathSource == WatchedFolderPathSource.ConnectionManager)
            {
                watchFolderPath = connections[this.WatchFolderPath].AcquireConnection(null) as string;
            }
            else if (this.WatchFolderPathSource == WatchedFolderPathSource.Variable)
            {
                Variables vars = null;
                variableDispenser.LockOneForRead(this.WatchFolderPath, ref vars);
                watchFolderPath = vars[this.WatchFolderPath].Value.ToString();
                vars.Unlock();
            }
            else
            {
                watchFolderPath = this.WatchFolderPath;
            }

            if (watchFolderPath.Length == 0 || !Directory.Exists(watchFolderPath))
            {
                events.FireError(0, "ForEachDirectory", "The WatchFolderPath is not provided or does not exist.", "", 0);
                return null;
            }

            string fileSpec = "";

            if (this.FileSpecSource == FileSpecSource.Variable)
            {
                Variables vars = null;
                variableDispenser.LockOneForRead(this.FileSpec, ref vars);
                fileSpec = vars[this.FileSpec].Value.ToString();
                vars.Unlock();
            }
            else
            {
                fileSpec = this.FileSpec;
            }

            return new WatchedDirectoryEnumerator(watchFolderPath, fileSpec, IncludeSubdirectories, TimeOut, ProcessExistingFiles).GetEnumerator();
        }



        public override DTSExecResult Validate(Connections connections, VariableDispenser variableDispenser, IDTSInfoEvents infoEvents, IDTSLogging log)
        {
            //if (!variableDispenser.Contains(this.timeOut))
            //{
            //    infoEvents.FireError(0, "MyEnumerator", "The Variable " + this.timeOut + " does not exist in the collection.", "", 0);
            //    return DTSExecResult.Failure;
            //}
            return DTSExecResult.Success;
        }

        #region IDTSComponentPersist
        public void SaveToXML(XmlDocument doc, IDTSInfoEvents infoEvents)
        {
            if (doc == null)
            {
                throw new ArgumentNullException("doc");
            }

            if (infoEvents == null)
            {
                throw new ArgumentNullException("infoEvents");
            }

            try
            {
                XmlElement eForEachDir = doc.CreateElement("ForEachWatchedFile");

                XmlElement eDirectory = doc.CreateElement("WatchFolderPath");
                eDirectory.InnerText = WatchFolderPath;
                eForEachDir.AppendChild(eDirectory);

                XmlElement eWatchFolderPathSource = doc.CreateElement("WatchFolderPathSource");
                eWatchFolderPathSource.InnerText = ((int)this.WatchFolderPathSource).ToString(CultureInfo.InstalledUICulture);
                eForEachDir.AppendChild(eWatchFolderPathSource);

                XmlElement eFileSpec = doc.CreateElement("FileSpec");
                eFileSpec.InnerText = FileSpec;
                eForEachDir.AppendChild(eFileSpec);

                XmlElement eFileSpecSource = doc.CreateElement("FileSpecSource");
                eFileSpecSource.InnerText = ((int)this.FileSpecSource).ToString(CultureInfo.InstalledUICulture);
                eForEachDir.AppendChild(eFileSpecSource);

                XmlElement eTimeOut = doc.CreateElement("TimeOut");
                eTimeOut.InnerText = TimeOut.ToString(CultureInfo.InvariantCulture);
                eForEachDir.AppendChild(eTimeOut);

                XmlElement eIncludeSubdirectories = doc.CreateElement("IncludeSubdirectories");
                eIncludeSubdirectories.InnerText = IncludeSubdirectories.ToString();
                eForEachDir.AppendChild(eIncludeSubdirectories);

                XmlElement eProcessExistingFiles = doc.CreateElement("ProcessExistingFiles");
                eProcessExistingFiles.InnerText = ProcessExistingFiles.ToString();
                eForEachDir.AppendChild(eProcessExistingFiles);

                doc.AppendChild(eForEachDir);
            }
            catch (System.Exception e)
            {
                infoEvents.FireError(0, "ForEachWatchedFile", e.Message, "", 0);
            }
        }

        public void LoadFromXML(XmlElement node, IDTSInfoEvents infoEvents)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (infoEvents == null)
            {
                throw new ArgumentNullException("infoEvents");
            }

            try
            {
                WatchFolderPath = node["WatchFolderPath"].InnerText;
                FileSpec = node["FileSpec"].InnerText;
                IncludeSubdirectories = Convert.ToBoolean(node["IncludeSubdirectories"].InnerText,
                    CultureInfo.InvariantCulture);
                ProcessExistingFiles = Convert.ToBoolean(node["ProcessExistingFiles"].InnerText,
                    CultureInfo.InvariantCulture);
                TimeOut = Convert.ToInt32(node["TimeOut"].InnerText,
                    CultureInfo.InvariantCulture);
                WatchFolderPathSource =
                    (WatchedFolderPathSource)(Convert.ToInt32(node["WatchFolderPathSource"].InnerText,
                        CultureInfo.InvariantCulture));
                FileSpecSource = (FileSpecSource) (Convert.ToInt32(node["FileSpecSource"].InnerText,
                    CultureInfo.InvariantCulture));
            }
            catch (System.Exception e)
            {
                infoEvents.FireError(0, "ForEachWatchedFile", e.Message, "", 0);
            }
        }

        #endregion
    }
}
